package com.scalar.chiptrack.workflow;

import com.jgraph.JGraph;
import com.jgraph.event.GraphSelectionEvent;
import com.jgraph.event.GraphSelectionListener;
import com.jgraph.graph.*;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import javax.swing.*;
import javax.swing.text.html.parser.ParserDelegator;
import javax.swing.event.UndoableEditEvent;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;

public class Editor extends JApplet implements GraphSelectionListener, KeyListener, MouseListener{

	protected JGraph graph;
	protected WorkflowModel model;
	protected XPDLPreview xpdl;
	protected String name;
	protected String productId;
	protected JPanel mainPanel;

	protected GraphUndoManager undoManager;
	protected JTabbedPane tabbedPane;
	protected JScrollPane scrollPane;
	protected String separator="#$#$#$";
	protected URL servletCodebase;
	private int errIndex = 0;
	protected Editor editor;
	protected String contextURL;
    protected String integrationType;
	static String mktgPartTitle;
    protected boolean userModifyPermission = false;
    protected boolean isDupMktgPartNumberAllowed = false;
    protected boolean isShowProductSetupFromDB = false;
    protected Object selectedCell;
    protected Object selectedCells[];

    protected int xCordinate = 10;
    protected int yCordinate = 10;

    private HashMap newPartNumberMap = new HashMap();

	protected Action undo,
		redo,
		remove,
		group,
		ungroup,
		tofront,
		toback,
		cut,
		copy,
		paste,
		SAVE,
        saveToFile,
        align,
        search, copyToclipboard,pasteclipboard;


    int interCell_h_gap = 50;
    int interCell_v_gap = 10;
    int cellWidth       = 100;
    int cellHeight      = 30;

    private  File getFile( String productName )
    {
		URL url;
		URLConnection con = null;
		String str = "getFile";
		ObjectOutputStream outStream;
		Document doc = null;
		File f = null;
        Boolean success = null;
		str = str + separator + productName;
		try
		{
			url = new URL( this.getContextURL() + "/WorkflowServlet");
			con = url.openConnection();
			if ( !con.getDoOutput() )
			{
				con.setDoOutput( true );
			}

			con.setDoInput( true );
			con.setUseCaches ( false );
			con.setDefaultUseCaches ( false );
			con.setAllowUserInteraction( true );
			con.setRequestProperty("CONTENT_LENGTH", "" + str.length());
			con.setRequestProperty ("Content-Type", "application/octet-stream");
			con.connect();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		try
		{
			outStream = new ObjectOutputStream( con.getOutputStream() );
			outStream.writeObject(str);
			outStream.flush();
			outStream.close();

			ObjectInputStream inputToApplet = null;
			inputToApplet = new ObjectInputStream( con.getInputStream() );
			try
			{                   
                if (isShowProductSetupFromDB )
                {
                    success = (Boolean)inputToApplet.readObject();
                }
                else
                {
                    f = ( File )inputToApplet.readObject();
                }
			}
			catch (ClassNotFoundException e2)
			{
				e2.printStackTrace();
			}
			inputToApplet.close();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
        return f;
    }

    public void init()
    {
		/*
		 * The following line is the workaround for the jre: 1.6.0_24 issue.
		  * see: http://stackoverflow.com/questions/4330602/html-no-longer-working-in-jlabel-and-other-components
		   * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6993691
		 */
		ParserDelegator workaround = new ParserDelegator();
		getContentPane().setLayout(new BorderLayout());
		this.editor 	= new Editor();
		name 			= getParameter("productName");
		contextURL 		= getParameter("contextURL");
		mktgPartTitle 	= getParameter("mktgPartTitle");
        integrationType = getParameter("integrationType");
        userModifyPermission = Boolean.valueOf( getParameter("userModifyPermission") ).booleanValue();
        isDupMktgPartNumberAllowed = Boolean.valueOf( getParameter("isDupMktgPartNumberAllowed") ).booleanValue();
        isShowProductSetupFromDB = Boolean.valueOf( getParameter("isShowProductSetupFromDB") ).booleanValue();
        editor.saveToFile.setEnabled( userModifyPermission );
        editor.SAVE.setEnabled( userModifyPermission );

        editor.setIntegrationType( integrationType );
		editor.setName(name);
		editor.setContextURL(contextURL);
        editor.setDupMktgPartNumberAllowed( isDupMktgPartNumberAllowed );
        getContentPane().add(editor);

		try
        {               
            if (isShowProductSetupFromDB)
            {
                getFile( name );
            }
			editor.getGraph().createWorkflow(contextURL+"/"+URLEncoder.encode(name,"UTF-8")+".xpdl", null);
		}
		catch( UnsupportedEncodingException uee )
		{
			System.out.println("UnsupportedEncodingException for encoding the file name");
		}
		// There is a Problem that the file is not refreshing when using URI
		// So commented the above code and fetching the file instead
		//editor.getGraph().createWorkflow( getFile( name ) );
	}

	public Editor() {
		getContentPane().setLayout(new BorderLayout());
		model = new WorkflowModel();
		model.setEditor(this);

		graph = new WorkflowGraph(model, this);

		// Create a GraphUndoManager which also Updates the ToolBar
		undoManager = new GraphUndoManager() {
				// Override Superclass
			public void undoableEditHappened(UndoableEditEvent e) {
					// First Invoke Superclass
					super.undoableEditHappened(e);
					// Then Update Undo/Redo Buttons
					updateHistoryButtons();
			}
		};

		graph.setCloneable( false );

		ToolTipManager.sharedInstance().registerComponent(graph);

		// Add Listeners to Graph
		//
		// Register UndoManager with the Model
		graph.getModel().addUndoableEditListener(undoManager);

		// Update ToolBar based on Selection Changes
		graph.getSelectionModel().addGraphSelectionListener(this);

		KeyListener listners[] = graph.getKeyListeners();
		for( int i = 0; i < listners.length; i++ )
		{
			graph.removeKeyListener( listners[i] );
		}

		// Listen for Delete Keystroke when the Graph has Focus
		graph.addKeyListener(this);

        graph.addMouseListener(this);

		JPanel panel = new JPanel();

      	panel.setLayout(new BorderLayout());

      	panel.add(createToolBar(), BorderLayout.NORTH);
    	panel.add(createCenterComponent(), BorderLayout.CENTER);

		mainPanel = new JPanel();
    	mainPanel.setLayout(new BorderLayout());
    	mainPanel.add(panel, BorderLayout.CENTER);
    	getContentPane().add( createContentTabbedPane(mainPanel), BorderLayout.CENTER );
	}

	public Component createCenterComponent()
	{
		scrollPane = new JScrollPane(graph,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS , JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

		JViewport port = scrollPane.getViewport();
		port.setScrollMode(JViewport.BLIT_SCROLL_MODE);
		return scrollPane;
	}

	public Component createContentTabbedPane(Component graphPanel)
	{
		/* Removed By Subramani 
	    xpdl = new XPDLPreview(this); */
		tabbedPane = new JTabbedPane(JTabbedPane.BOTTOM);
		tabbedPane.addTab("Graph View", graphPanel);
		/* Removed By Subramani 
		tabbedPane.addTab("XPDL View", xpdl);

		tabbedPane.addChangeListener(new ChangeListener() {
         public void stateChanged (ChangeEvent ce) {
         	if (tabbedPane.getSelectedIndex()==1) {
               	xpdl.refreshView(model);
            }
         }
      });*/
		return tabbedPane;
	}

	public WorkflowGraph getGraph()
	{
		return (WorkflowGraph)graph;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public String getName()
	{
		return name;
	}

	public void setProductId(String productId)
	{
		this.productId = productId;
	}

	public String getProductId()
	{
		return productId;
	}

	public String getContextURL(){
		return contextURL;
	}

    public boolean isDupMktgPartNumberAllowed(){
		return isDupMktgPartNumberAllowed;
	}
    public void setDupMktgPartNumberAllowed(boolean isDupMktgPartNumberAllowed){
		this.isDupMktgPartNumberAllowed = isDupMktgPartNumberAllowed;
	}

    public void setContextURL(String contextURL){
		this.contextURL = contextURL;
	}
    public String getIntegrationType(){
		return integrationType;
	}

	public void setIntegrationType(String integrationType){
		this.integrationType = integrationType;
	}

	//end adding

	// Insert a new Vertex at point
	public void insert(Point point) {
		// Construct Vertex with no Label
		DefaultGraphCell vertex = new DefaultGraphCell();
		// Add one Floating Port
		vertex.add(new DefaultPort());
		// Snap the Point to the Grid
		point = graph.snap(new Point(point));
		// Default Size for the new Vertex
		Dimension size = new Dimension(70, 30);
		// Create a Map that holds the attributes for the Vertex
		Map map = GraphConstants.createMap();

		//GraphConstants.applyMap(testMap, map);
		// Add a Bounds Attribute to the Map
		GraphConstants.setBounds(map, new Rectangle(point, size));
		// Add a Border Color Attribute to the Map
		GraphConstants.setBorderColor(map, Color.black);
		// Add a White Background
		//GraphConstants.setBackground(map, Color.white);

		GraphConstants.setBackground(map, new Color(213, 221, 253));
		// Make Vertex Opaque
		GraphConstants.setOpaque(map, true);
		GraphConstants.setValue(map, "Process");
        map.put ( "attrId", "TEMP_"+ System.currentTimeMillis() );
		// Construct a Map from cells to Maps (for insert)
		Hashtable attributes = new Hashtable();
		// Associate the Vertex with its Attributes
		attributes.put(vertex, map);
		// Insert the Vertex and its Attributes (can also use model)
		graph.getGraphLayoutCache().insert(
			new Object[] { vertex },
			attributes,
			null,
			null,
			null);
	}

	// Insert a new Edge between source and target
	public void connect(Port source, Port target) {

        DefaultGraphCell sourceCell = (DefaultGraphCell)((DefaultPort)source).getParent();
        DefaultGraphCell targetCell = (DefaultGraphCell)((DefaultPort)target).getParent();
        String sourceId = (String)sourceCell.getAttributes().get("attrId");
        String targetId = (String)targetCell.getAttributes().get("attrId");

        Iterator sourceEdgesIterator = source.edges();
        while( sourceEdgesIterator.hasNext() )
        {
            DefaultEdge edge = (DefaultEdge)sourceEdgesIterator.next();
            String edgeSourceId = (String)edge.getAttributes().get("From");
            String edgeTargetId = (String)edge.getAttributes().get("To");
            //Checking Edge exists or not
            if ( sourceId.equals( edgeSourceId ) && targetId.equals( edgeTargetId ) )
            {
                return; //Edge already exists
            }
        }
		// Connections that will be inserted into the Model
		ConnectionSet cs = new ConnectionSet();
		// Construct Edge with no label
		DefaultEdge edge = new DefaultEdge();
		// Create Connection between source and target using edge
		cs.connect(edge, source, target);
		// Create a Map thath holds the attributes for the edge
		Map map = GraphConstants.createMap();
		map.put("transitionStepId","");
        map.put ( "From", sourceCell.getAttributes().get("attrId") );
        map.put ( "To", targetCell.getAttributes().get("attrId") );
		//map.put("bounds", new Rectangle(10,10,20,20));
		// Add a Line End Attribute
		GraphConstants.setLineEnd(map, GraphConstants.ARROW_TECHNICAL);
		// Construct a Map from cells to Maps (for insert)
		Hashtable attributes = new Hashtable();
		// Associate the Edge with its Attributes
		attributes.put(edge, map);
		// Insert the Edge and its Attributes
		graph.getGraphLayoutCache().insert(
			new Object[] { edge },
			attributes,
			cs,
			null,
			null);
	}

	public boolean save( String location  )
	{
		boolean success = false;
		try
		{
         	String temp = getXPDL(null,null, null );
         	temp = temp + separator + location + separator + name;
            success = writeDocument( temp );

			//mainPanel.invalidate();
			///mainPanel.validate();
			//getContentPane().invalidate();
			//getContentPane().validate();
			//getGraph().invalidate();
			//getGraph().validate();
         }
		 catch(NullPointerException e)
		 {
	 		e.printStackTrace();
		 } catch (TransformerException e)
		 {
		    e.printStackTrace();
		 } catch (ParserConfigurationException e)
		 {
		    e.printStackTrace();
		 }
		 //if( enableSave == 1 )
		 //{
		 //	saveButton.addActionListener( this );
		 //}
		 return success;
	}

    public boolean save( String location, ArrayList cellsList, ArrayList edgesList  )
	{
		boolean success = false;
		try
		{
         	String temp = getXPDL(location, cellsList, edgesList );
         	temp = temp + separator + location + separator + "clipboard";
            success = writeDocument( temp );

			//mainPanel.invalidate();
			///mainPanel.validate();
			//getContentPane().invalidate();
			//getContentPane().validate();
			//getGraph().invalidate();
			//getGraph().validate();
         }
		 catch(NullPointerException e)
		 {
	 		e.printStackTrace();
		 } catch (TransformerException e)
		 {
		    e.printStackTrace();
		 } catch (ParserConfigurationException e)
		 {
		    e.printStackTrace();
		 }
		 //if( enableSave == 1 )
		 //{
		 //	saveButton.addActionListener( this );
		 //}
		 return success;
	}

    public String getXPDL(String location, ArrayList attributesList, ArrayList edgesList ) throws ParserConfigurationException, TransformerException
    {
        mainPanel.validate();
        Document document = null;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = dbf.newDocumentBuilder();

        document = builder.newDocument();
        CharArrayWriter caw = new CharArrayWriter();
        getGraph().getWorkflowManager().toXML(document,  attributesList, edgesList, location );
        TransformerFactory tFactory = TransformerFactory.newInstance();
        Transformer transformer = tFactory.newTransformer();
        transformer.setOutputProperty( "version", "1.0" );
        transformer.setOutputProperty( "encoding", "UTF-8" );
        transformer.setOutputProperty( "indent", "yes" );
        transformer.setOutputProperty( "{https://xml.apache.org/xslt}indent-amount","4");

        DOMSource source = new DOMSource( document );
        StreamResult result = new StreamResult( caw );
        transformer.transform( source ,result );
        String temp = new String(caw.toCharArray());
        return temp;
    }


    /**
     * method to align the process flow
     */
    public void align()
    {
        int choice = JOptionPane.showConfirmDialog(null,"Once the graph is aligned, it cannot be undone! \nTo revert, please go back and reload the graph.","Chiptrac Confirmation",JOptionPane.OK_CANCEL_OPTION);

        // in case the user chooses not to align the graph
        if( choice == 2)
        {
            return;
        }
        try
        {

            // represents the X and Y Coordinates of the Root Activity
            int absXForRoot = 0;
            int absYForRoot = 170;

            // get all the Activities of the graph
            ArrayList activitiesList = ((WorkflowGraph)graph).getWorkflowManager().getActivities();

            // build a hashMap using the arrayList activitiesList.
            // the hashMap will have the 'attrId' attribute of the activity as KEY and CustomActivity as VALUE
            HashMap activitiesMap = buildActivitiesMap( activitiesList );

            DefaultGraphCell dgc_rootActivity = null;
            CustomActivity ca_rootActivity = new CustomActivity();
            dgc_rootActivity = (DefaultGraphCell) model.getFirstCell();
            constructCustomActivity( dgc_rootActivity, ca_rootActivity, false);
            ca_rootActivity.setRefCustomActivity( ca_rootActivity);
            ca_rootActivity.setAbsX( absXForRoot);
            ca_rootActivity.setAbsY( absYForRoot);

            // each element in ca_levelList is an arrayList and stores all the activities present in that level
            ArrayList ca_levelList = new ArrayList();
            ArrayList ca_activitiesList = new ArrayList();
            ca_activitiesList.add( ca_rootActivity);
            ca_levelList.add( ca_activitiesList);

            /**
            * each element in the maxChildren arrayList is the maximum number of children present in that level for any
            * Activity in the previous level
            */
            ArrayList maxChildren = new ArrayList();
            maxChildren.add( new Integer(0));

            /**
             * each activity is processed ie.,
             * 1. A flag is set which tells if the activity is Relatively positioned or Absolutely positioned.
             * 2. Every Activity's 'children' ArrayList is filled with all the children it has and which are not processed
             * 3. The Relative Y position of the Activity  assigned if it the first child and if it is not processed
             */
            processActivities( ca_levelList, activitiesMap, maxChildren, ca_rootActivity, 0);

            // A reference to the previuos Activity in the same level is stored
            setRefToPrevActivityInSameLevel( ca_levelList);

            // calculate the Y Coordinate for all the Activities
            setYcoordinate( (CustomActivity)((ArrayList)ca_levelList.get(0)).get(0) );

            // calculate the X Coordinate for all the Activities
            setXcoordinate( ca_levelList, maxChildren);

            // remove the current edges and cells from the graph, and use the once we modified and redraw the graph
            ArrayList edgeList = model.getAllEdges();
            ArrayList activityList = model.getAllCells();

            ArrayList activityCollection = (ArrayList) ((WorkflowGraph)graph).getWorkflowManager().getActivities().clone();
            ArrayList transitionCollection = (ArrayList)((WorkflowGraph)graph).getWorkflowManager().getAllTransitions().clone();

            Object[] cells = edgeList.toArray();
            cells = graph.getDescendants(cells);
            graph.getModel().remove(cells);

            cells = activityList.toArray();
            cells = graph.getDescendants(cells);
            graph.getModel().remove(cells);
            getGraph().validate();

            Map mapCopy;
            DefaultGraphCell cell;
            Object newCells[] = new Object[activityCollection.size()];
            int cellNo = 0;
            Iterator it = activityCollection.iterator();
            while(it.hasNext()){
                cell = ( DefaultGraphCell ) it.next();
                mapCopy = cell.getAttributes();
                getGraph().getWorkflowManager().insertActivities(mapCopy, newCells, null, cellNo++);
            }
            Object newEdges[] = new Object[transitionCollection.size()];
            int edgeNo = 0;
            it = transitionCollection.iterator();
            while(it.hasNext())
            {
                cell = ( DefaultGraphCell ) it.next();
                mapCopy = cell.getAttributes();
                getGraph().getWorkflowManager().insertTransitions(mapCopy, newEdges, null, edgeNo++ );
            }
        }
        catch( Exception e)
        {
            e.printStackTrace();
        }
    }

    public boolean search( String searchPartNumber )
    {
        ArrayList activityList = model.getAllCells();
        DefaultGraphCell cell;
        Iterator it = activityList.iterator();
        Map attrbts = null;
        Hashtable ht = new Hashtable();
        boolean found = false;
        while(it.hasNext())
        {
            cell = ( DefaultGraphCell ) it.next();
            attrbts = cell.getAttributes();
            String partNumber = (String)attrbts.get( "partnumber" );
            if ( searchPartNumber != null && partNumber!= null && partNumber.toUpperCase().indexOf( searchPartNumber.toUpperCase() ) != -1 )
            {
                found = true;
                //GraphConstants.setBorderColor(attrbts, Color.BLUE);
                GraphConstants.setBorder( attrbts, BorderFactory.createLineBorder( Color.BLUE, 2 ) );
            }
            else
            {
                attrbts.remove( "border" );
            }
            ht.put ( cell, attrbts );
        }
        graph.getGraphLayoutCache().edit( ht, null, null, null );
        ht = null;
        return found;
    }

    /**
     *
     * @param activitiesList - has all the activities in the form of DefaultGraphCell
     * returns activitiesMap  - has all the activities wrapped in CustomActivity. the KEY is the DefaultGraphCell's
     * 'attrId' attribute attribute and the VALUE is the CustomActivity that is created
     *
     */
    private HashMap buildActivitiesMap( ArrayList activitiesList)
    {
        HashMap activitiesMap = new HashMap();
        if ( activitiesList != null && !activitiesList.isEmpty() )
        {
            Iterator i = activitiesList.iterator();
            while( i.hasNext() )
            {
                DefaultGraphCell dgc_cell = (DefaultGraphCell) i.next();
                CustomActivity ca_cell = new CustomActivity();
                constructCustomActivity(dgc_cell, ca_cell, false);
                Map aMap = dgc_cell.getAttributes();
                activitiesMap.put(aMap.get("attrId"), ca_cell );
            }
            //System.out.println("activitiesMap : " + activitiesMap);
        }
        return activitiesMap;
    }

    /**
     *
     * @param dfg
     * @param ca
     * @param forParent when true will set only parent details
     * this method stores the details of DefaultGraphCell in CustomActivity ( Wrapper class to DefaultGraphCell)
     */
    private void constructCustomActivity( DefaultGraphCell dfg, CustomActivity ca, boolean forParent)
    {
        if( !forParent)
        {
            ca.setActivity( dfg);
            Map aMap = (Map) dfg.getAttributes();
            ca.setAttribs(aMap);
            ca.setBounds( (Rectangle) aMap.get("bounds"));
        }
        else
        {
            ca.setParentActivity( dfg );
            Map aMap = (Map) dfg.getAttributes();
            ca.setParentAttribs( aMap );
            ca.setParentBounds( (Rectangle)aMap.get("bounds"));
        }
    }

    /**
     *
     * @param ca_levelList
     * @param activitiesMap
     * @param maxChildren
     * @param ca_currentActivity
     * @param level
     *
     * each activity is processed ie.,
     * 1. A flag is set which tells if the activity is Relatively positioned or Absolutely positioned.
     * 2. Every Activity's 'children' ArrayList is filled with all the children it has and which are not processed
     * 3. The Relative Y position of the Activity  assigned if it the first child and if it is not processed
     *
     */
    private void processActivities(ArrayList ca_levelList, HashMap activitiesMap,ArrayList maxChildren, CustomActivity ca_currentActivity, int level)
    {
        int nextLevel = level + 1;
        Rectangle bounds = ca_currentActivity.getBounds();
        bounds.width = cellWidth;
        bounds.height = cellHeight;

        Set ca_currentActivityOutbounds = model.getOutgoingTransitions( ca_currentActivity.getActivity() );

        /**
         * ca_currentActivityOutbounds is a Set which will not return the elements in the same order for every access
         * To prevent the change of graph view every time align() is called, these activities are sorted using the
         * 'attrId' attribute of the activity
         **/
        ArrayList outboundsList = getSortedArrayList( ca_currentActivityOutbounds);

        int nbrOfchildren = outboundsList.size();

        Iterator outboundsItr = outboundsList.iterator();
        int childCount = 0;
        while( outboundsItr.hasNext() )
        {
            DefaultEdge edge = (DefaultEdge) outboundsItr.next();
            Map tMap = edge.getAttributes();
            //System.out.println(""+ tMap.get("To"));
            CustomActivity ca_targetActivity = (CustomActivity) activitiesMap.get( tMap.get("To"));
            if( !ca_targetActivity.isProcessed())
            {
                childCount++;
            }
        }

        //the childcount here is not the actual child count but the no of children whose isProcessed is false.
        int relY = 0-(((((childCount-1)*interCell_v_gap) + childCount*cellHeight)/2)-(cellHeight/2));
        ArrayList ca_nextLevelActivities = null;
        if( nextLevel >= ca_levelList.size() && !outboundsList.isEmpty() )
        {
            ca_nextLevelActivities = new ArrayList();
            ca_levelList.add( nextLevel, ca_nextLevelActivities);
        }
        else
        {
            if( nextLevel < ca_levelList.size())
            {
                ca_nextLevelActivities = (ArrayList) ( ca_levelList.get( nextLevel));
            }
        }

        outboundsItr = outboundsList.iterator();
        if( maxChildren.size() > nextLevel )
        {
            int curMaxChildren = ((Integer) maxChildren.get( nextLevel)).intValue();
            if( curMaxChildren < nbrOfchildren )
            {
                maxChildren.set( nextLevel, new Integer(nbrOfchildren) );
            }
        }
        else
        {
            maxChildren.add( new Integer(nbrOfchildren));
        }

        if( outboundsList.isEmpty() )
        {
            return;
        }
        while( outboundsItr.hasNext())
        {
            DefaultEdge edge = (DefaultEdge) outboundsItr.next();
            Map tMap = edge.getAttributes();
            CustomActivity ca_targetActivity = (CustomActivity) activitiesMap.get( tMap.get("To"));
            if( !ca_nextLevelActivities.contains( ca_targetActivity) && !ca_targetActivity.isProcessed())
            {
                constructCustomActivity( ca_currentActivity.getActivity(), ca_targetActivity, true );
                ca_targetActivity.setCa_parent( ca_currentActivity);
                if( ca_currentActivity.getChildren() != null)
                {
                    ca_currentActivity.getChildren().add( ca_targetActivity);
                    ca_targetActivity.setRefCustomActivity( ca_targetActivity);
                }
                else
                {
                    ca_targetActivity.setRelY( relY);
                    ca_targetActivity.setRefCustomActivity(ca_currentActivity.getRefCustomActivity());
                    ca_targetActivity.setAbsolutePositioned( false);
                    ArrayList currentActivityChildren = new ArrayList();
                    currentActivityChildren.add( ca_targetActivity);
                    ca_currentActivity.setChildren( currentActivityChildren );
                }
                ca_targetActivity.setProcessed( true);
                ca_nextLevelActivities.add( ca_targetActivity);
            }
            processActivities( ca_levelList, activitiesMap, maxChildren, ca_targetActivity, level+1);
        }
    }

    /**
     *
     * @param ca_levelList set the reference to the sibling in each activity
     */
    private void setRefToPrevActivityInSameLevel( ArrayList ca_levelList)
    {
        for( int i = 0; i < ca_levelList.size(); i++)
        {
            ArrayList activities =(ArrayList) ca_levelList.get(i);
            for( int j = 1; j < activities.size(); j++)
            {
                CustomActivity activity = (CustomActivity) activities.get( j);
                activity.setCa_prevSibling( (CustomActivity)activities.get( j-1));
            }
        }
    }

    /**
     *
     * @param ca_activity
     * processes each node and assigns it the Y coordinate
     */
    private void setYcoordinate( CustomActivity ca_activity )
    {
        if( ca_activity.isAbsolutePositioned() )
        {
            CustomActivity ca_parentActivity = ca_activity.getCa_parent();
            if( ca_parentActivity != null )
            {
                if(ca_activity.getCa_prevSibling() != null )
                {
                    int prevSiblingY = ca_activity.getCa_prevSibling().getAbsY();
                    ca_activity.setAbsY( prevSiblingY + cellHeight  + interCell_v_gap );
                }
            }
        }
        else
        {
            CustomActivity ca_parentActivity = ca_activity.getCa_parent();
            int tmpY = 0;
            if( ca_parentActivity != null)
            {
                tmpY = ca_parentActivity.getAbsY()+ca_activity.getRelY();
                if( tmpY < 0 )
                {
                    int ca_refAbsY = ca_activity.getRefCustomActivity().getAbsY();
                    ca_activity.getRefCustomActivity().setAbsY( ca_refAbsY + Math.abs( tmpY ) + interCell_v_gap );
                }
                CustomActivity ca_prevSibling = ca_activity.getCa_prevSibling();
                int prevSiblingY = 0;
                if( ca_prevSibling != null)
                {
                    prevSiblingY = ca_prevSibling.getAbsY() + cellHeight;
                    if ( tmpY <= prevSiblingY)
                    {
                        int ca_refAbsY = ca_activity.getRefCustomActivity().getAbsY();
                        ca_activity.getRefCustomActivity().setAbsY( ca_refAbsY + ((prevSiblingY - tmpY) + interCell_v_gap ));
                    }
                }
            }
        }
        if( ca_activity.getChildren() == null || ca_activity.getChildren().isEmpty() )
        {
            return;
        }
        Iterator ca_childrenIte = ca_activity.getChildren().iterator();
        while( ca_childrenIte.hasNext() )
        {
            setYcoordinate( (CustomActivity) ca_childrenIte.next());
        }
    }

    /**
     *
     * @param ca_levelList
     * @param maxChildren
     * processes each activity and asigns it the X coordinate
     *
     */
     private void setXcoordinate(ArrayList ca_levelList,ArrayList maxChildren)
    {
        int prevLevelX = 0;
        for( int i = 0; i < ca_levelList.size(); i++)
        {
            ArrayList ca_activities = (ArrayList) ca_levelList.get( i);
            int maxChilds = ((Integer)maxChildren.get( i)).intValue();
            Iterator ca_activitiesIter = ca_activities.iterator();
            int tmpPrevX = 0;
            while( ca_activitiesIter.hasNext() )
            {
                CustomActivity ca_currentActivity = (CustomActivity) ca_activitiesIter.next();
                CustomActivity ca_parentActivity = ca_currentActivity.getCa_parent();
                if( ca_parentActivity != null )
                {

                    if( !ca_currentActivity.isAbsolutePositioned() && ca_currentActivity.getRefCustomActivity() != null )
                    {
                        ca_currentActivity.bounds.y = ca_currentActivity.getAbsY();
                    }
                    else
                    {
                        ca_currentActivity.bounds.y =ca_currentActivity.getAbsY();
                    }
                    ca_currentActivity.bounds.x =(prevLevelX+((int)( maxChilds*interCell_h_gap))+cellWidth);
                    tmpPrevX = (prevLevelX+((int)( maxChilds*interCell_h_gap))+cellWidth);
                }
                else
                {
                    ca_currentActivity.bounds.x = ca_currentActivity.getAbsX();
                    ca_currentActivity.bounds.y = ca_currentActivity.getAbsY();
                    prevLevelX = ca_currentActivity.getAbsX();
                }
            }
            prevLevelX = tmpPrevX;
        }
    }

    /**
     *
     * @param outboundsSet
     * @return
     *
     */
    private ArrayList getSortedArrayList( Set outboundsSet )
    {
        Object outbounds[] = outboundsSet.toArray();
        Object tmpObj;
        for( int i=0; i<outbounds.length-1; i++)
        {
            int min = i;
            for( int j = i+1; j<outbounds.length; j++)
            {
                int tmpNbr1 = getActivityNbr( outbounds[min]);
                int tmpNbr2 = getActivityNbr( outbounds[j]);
                if( tmpNbr2 < tmpNbr1 )
                {
                    min = j;
                }
            }
            tmpObj = outbounds[i];
            outbounds[i] = outbounds[min];
            outbounds[min] = tmpObj;
        }

        ArrayList outboundsList = new ArrayList();
        for( int i = 0; i<outbounds.length; i++)
        {
            //System.out.println(((DefaultEdge)outbounds[i]).getAttributes().get("To"));
            outboundsList.add( outbounds[i]);
        }
        return outboundsList;
    }

    /**
     *
     * @param activity
     * @return
     *
     */
    private int getActivityNbr( Object activity )
    {
        String tmpStr = (String)((DefaultEdge)activity).getAttributes().get("To");
        tmpStr = tmpStr.substring( tmpStr.lastIndexOf("_")+1 );
        int tmpNbr;
        try
        {
            tmpNbr = Integer.parseInt(tmpStr);
        }
        catch ( NumberFormatException e )
        {
            tmpNbr = 0;
        }
        return tmpNbr;
    }


	/**
     * @param strDoc
     */
	private boolean writeDocument(String strDoc)
    {
		URL url;
		URLConnection con = null;
		String str = "";
		boolean success = false;
		ObjectOutputStream outStream;
		try
		{
			url = new URL(this.getContextURL()+"/WorkflowServlet");
			con = url.openConnection();
			if ( !con.getDoOutput() )
			{
				con.setDoOutput( true );
			}

			con.setDoInput( true );
			con.setUseCaches ( false );
			con.setDefaultUseCaches ( false );
			con.setAllowUserInteraction( true );
			con.setRequestProperty ("Content-Type", "application/octet-stream");
			con.connect();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		try
		{
			outStream = new ObjectOutputStream( con.getOutputStream());
			outStream.writeObject( strDoc );
			outStream.flush();
			outStream.close();

			ObjectInputStream inputToApplet = null;
			inputToApplet = new ObjectInputStream( con.getInputStream() );
			try
			{
				str = ( String )inputToApplet.readObject();
			}
			catch (ClassNotFoundException e2)
			{
				e2.printStackTrace();
			}
			inputToApplet.close();

			if( str.equals( "success" ) )
			{
				ArrayList edgeList = model.getAllEdges();
				ArrayList activityList = model.getAllCells();

				Object[] cells = edgeList.toArray();
				cells = graph.getDescendants(cells);
				graph.getModel().remove(cells);

				cells = activityList.toArray();
				cells = graph.getDescendants(cells);
				graph.getModel().remove(cells);
				//getGraph().removeAll();
				//getGraph().invalidate();
				getGraph().validate();

				//File file = getFile( name );
				//getGraph().createWorkflow( file );

				getGraph().createWorkflow( this.getContextURL()+"/"+URLEncoder.encode(name,"UTF-8")+".xpdl", null);
				getGraph().validate();
				success = true;
			}
			else
			{
				//JOptionPane.showMessageDialog(null,"Not able to save the data ","Chiptrac Error",JOptionPane.ERROR_MESSAGE);
                if ( str == null || str.trim().length() == 0 || str.trim().equalsIgnoreCase("failure") )
                {
                     str =  "Not able to save the data ";
                }
                else
                {
                    str = str + "\nNot able to save the data ";
                }
                JOptionPane.showMessageDialog(null,str,"Chiptrac Error",JOptionPane.ERROR_MESSAGE);
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

		return success;
    }

    // Create a Group that Contains the Cells
	public void group(Object[] cells)
	{
		// Order Cells by View Layering
		cells = graph.getGraphLayoutCache().order(cells);

		if (cells != null && cells.length > 0)
		{
			// Create Group Cell
			int count = getCellCount(graph);
			DefaultGraphCell group = new DefaultGraphCell(new Integer(count - 1));
			// Create Change Information
			ParentMap map = new ParentMap();
			// Insert Child Parent Entries
			for (int i = 0; i < cells.length; i++)
				map.addEntry(cells[i], group);
			// Insert into model
			graph.getGraphLayoutCache().insert(
				new Object[] { group },
				null,
				null,
				map,
				null);
		}
	}

	// Returns the total number of cells in a graph
	protected int getCellCount(JGraph graph) {
		Object[] cells = graph.getDescendants(graph.getRoots());
		return cells.length;
	}

	// Ungroup the Groups in Cells and Select the Children
	public void ungroup(Object[] cells) {
		// If any Cells
		if (cells != null && cells.length > 0) {
			// List that Holds the Groups
			ArrayList groups = new ArrayList();
			// List that Holds the Children
			ArrayList children = new ArrayList();
			// Loop Cells
			for (int i = 0; i < cells.length; i++) {
				// If Cell is a Group
				if (isGroup(cells[i])) {
					// Add to List of Groups
					groups.add(cells[i]);
					// Loop Children of Cell
					for (int j = 0; j < graph.getModel().getChildCount(cells[i]); j++) {
						// Get Child from Model
						Object child = graph.getModel().getChild(cells[i], j);
						// If Not Port
						if (!(child instanceof Port))
							// Add to Children List
							children.add(child);
					}
				}
			}
			// Remove Groups from Model (Without Children)
			graph.getGraphLayoutCache().remove(groups.toArray());
			// Select Children
			graph.setSelectionCells(children.toArray());
		}
	}

	// Determines if a Cell is a Group
	public boolean isGroup(Object cell) {
		// Map the Cell to its View
		CellView view = graph.getGraphLayoutCache().getMapping(cell, false);
		if (view != null)
			return !view.isLeaf();
		return false;
	}

	// Brings the Specified Cells to Front
	public void toFront(Object[] c) {
		graph.getGraphLayoutCache().toFront(c);
	}

	// Sends the Specified Cells to Back
	public void toBack(Object[] c) {
		graph.getGraphLayoutCache().toBack(c);
	}

	// Undo the last Change to the Model or the View
	public void undo() {
		try {
            int cellsWithProcessStepIDCountBeforeUndo = 0;    //represents total number of Processes having process stepid
            int edgesSavedCountBeforeUndo = 0;                //represents total number of Edges that were saved

            int cellsWithProcessStepIDCountAfterUndo = 0;    //represents total number of Processes having process stepid
            int edgesSavedCountAfterUndo = 0;                //represents total number of Edges that were saved

            DefaultGraphCell cell;
            DefaultEdge edge;
            Map map;

            ArrayList activityList = model.getAllCells();

            for (int i=0; i < activityList.size(); i++)
            {
                cell = (DefaultGraphCell)activityList.get(i);
                map = cell.getAttributes();
                if ( map.get( "processStepId") != null && ((String)map.get( "processStepId")).trim().length() >0 )
                {
                    cellsWithProcessStepIDCountBeforeUndo++;
                }
            }

            activityList = model.getAllEdges();

            for (int i=0; i < activityList.size(); i++)
            {
                edge = (DefaultEdge)activityList.get(i);
                map = edge.getAttributes();
                if ( map.get( "value") != null )    //if the edge having Name (map contains "value" attribute) means,
                {                                   //edge not yet saved.
                    edgesSavedCountBeforeUndo++;
                }
            }

			undoManager.undo(graph.getGraphLayoutCache());

            activityList = model.getAllCells();

            for (int i=0; i < activityList.size(); i++)
            {
                cell = (DefaultGraphCell)activityList.get(i);
                map = cell.getAttributes();
                if ( map.get( "processStepId") != null && ((String)map.get( "processStepId")).trim().length() >0 )
                {
                    cellsWithProcessStepIDCountAfterUndo++;
                }
            }

            activityList = model.getAllEdges();

            for (int i=0; i < activityList.size(); i++)
            {
                edge = (DefaultEdge)activityList.get(i);
                map = edge.getAttributes();
                if ( map.get( "value") != null )    //if the edge having Name (map contains "value" attribute) means,
                {                                   //edge not yet saved.
                    edgesSavedCountAfterUndo++;
                }
            }

            //bringing back the processes (having process step ids) and transitions already saved even we press undo.
            if ( (cellsWithProcessStepIDCountBeforeUndo > cellsWithProcessStepIDCountAfterUndo) || (edgesSavedCountBeforeUndo > edgesSavedCountAfterUndo) )
            {
                redo();
            }

		} catch (Exception ex) {
			System.err.println(ex);
		} finally {
			updateHistoryButtons();
		}
	}

	// Redo the last Change to the Model or the View
	public void redo() {
		try {
			undoManager.redo(graph.getGraphLayoutCache());
		} catch (Exception ex) {
			System.err.println(ex);
		} finally {
			updateHistoryButtons();
		}
	}

	// Update Undo/Redo Button State based on Undo Manager
	protected void updateHistoryButtons() {
		// The View Argument Defines the Context
		undo.setEnabled(undoManager.canUndo(graph.getGraphLayoutCache()));
		redo.setEnabled(undoManager.canRedo(graph.getGraphLayoutCache()));
	}

	public void paste(String type)
	{
		if( selectedCells != null )
		{
            int selectedCellsCount = selectedCells.length;
            Object newCells[] = new Object[selectedCellsCount];
            Map newCellMap = new HashMap();

            for ( int i=0; i < selectedCellsCount; i++ )
            {
                selectedCell = selectedCells[i];
                
                if( selectedCell instanceof DefaultGraphCell )
                {
                    DefaultGraphCell cell = (DefaultGraphCell)selectedCell;
                    Map cellAttributes = cell.getAttributes();
                    DefaultGraphCell newCell = new DefaultGraphCell();
                    newCell.add(new DefaultPort());
                    Map map = GraphConstants.createMap();
                    if( cellAttributes != null && !cellAttributes.isEmpty())
                    {
                        Iterator it = cellAttributes.keySet().iterator();
                        while ( it.hasNext() )
                        {
                            Object temp = it.next();
                            map.put( temp, cellAttributes.get( temp ) );
                        }
                        // This is not working here need to check later
                        //cellAttributes.putAll( map );
                    }
                    //System.out.println("map.containsKey(processStepId) = " + map.containsKey("processStepId"));
                    // Make the processStepId to null
                    if( map.containsKey( "processStepId" ) )
                    {
                        //map.put( "processStepId", "" );
                        String copiedFromProcessStepId = (String)map.get( "processStepId" );
                        map.remove( "processStepId" );
                        if ( copiedFromProcessStepId != null && copiedFromProcessStepId.trim().length() > 0 )
                        {
                            Map activityAttributesMap = PopupPanel.getActivityAttributesMap( copiedFromProcessStepId, (WorkflowGraph)graph );
                            if ( activityAttributesMap != null )
                            {
                                map.putAll( activityAttributesMap );
                            }
                        }
                    }

                    // set the new cell position 20 units below the selected cell
                    if( map.containsKey("bounds")  )
                    {
                        Rectangle r = (Rectangle)map.get("bounds");
                        if ("clipboard".equalsIgnoreCase( type ) )
                        {
                            map.put( "bounds", new Rectangle( r.x, r.y+30, r.width, r.height )  );
                        }
                        else
                        map.put( "bounds", new Rectangle( r.x, r.y+30, r.width, r.height )  );
                    }

                    // set the back ground color to blue because processStepId is null
                    GraphConstants.setBackground(map, new Color(213, 221, 253));
                    //set the attrId to be distinct
                    map.put ( "attrId", "TEMP_"+ System.currentTimeMillis() );

                    Hashtable attributes = new Hashtable();
                    attributes.put( newCell, map );
                    graph.getGraphLayoutCache().insert(
                        new Object[] { newCell },
                        attributes,
                        null,
                        null,
                        null);
                    newCellMap.put(cell, newCell);
                    newCells[i] = newCell;
                }
                if ( selectedCell instanceof DefaultEdge )
                {
                    //selectedEdges[i] = selectedCell;

                    DefaultEdge edge = (DefaultEdge)selectedCell;
                    if ( edge != null )
                    {
                        ConnectionSet cs = new ConnectionSet();
                        DefaultEdge newEdge = new DefaultEdge();

                        Object newSource = newCellMap.get ( ((DefaultPort)edge.getSource()).getParent() );
                        Object newTarget = newCellMap.get ( ((DefaultPort)edge.getTarget()).getParent() );
                        if ( newSource != null && newTarget != null )
                        {
                            String sourceId = (String)((DefaultGraphCell)newSource).getAttributes().get("attrId");
                            String targetId = (String)((DefaultGraphCell)newTarget).getAttributes().get("attrId");

                            DefaultPort sourcePort = ((WorkflowModel)graph.getModel()).getPort(newSource);
                            DefaultPort targetPort = ((WorkflowModel)graph.getModel()).getPort(newTarget);
                            // Create Connection between source and target using edge
                            cs.connect(newEdge, sourcePort, targetPort );
                            Map map = GraphConstants.createMap();
                            Map cellAttributes = edge.getAttributes();
                            if( cellAttributes != null && !cellAttributes.isEmpty())
                            {
                                Iterator it = cellAttributes.keySet().iterator();
                                while ( it.hasNext() )
                                {
                                    Object temp = it.next();
                                    map.put( temp, cellAttributes.get( temp ) );
                                }
                            }
                            
                            map.put ( "From", sourceId );
                            map.put ( "To", targetId );
                            Hashtable attributes = new Hashtable();
                            attributes.put( newEdge, map );
                            // Insert the Edge and its Attributes
                            graph.getGraphLayoutCache().insert(
                                new Object[] { newEdge },
                                attributes,
                                cs,
                                null,
                                null);
                            newCells[i] = newEdge;
                        }
                        else
                        {
                            System.out.println ( "Could Not Create an Edge:" + (newSource == null ? " Source is Null" : ":") + (newTarget == null ? "Target is Null" : ":" ) );
                        }
                    }
                }
                /*if( selectedCell instanceof DefaultGraphCell )
                {
                    DefaultGraphCell cell = (DefaultGraphCell)selectedCell;
                    Map cellAttributes = cell.getAttributes();
                    DefaultGraphCell newCell = new DefaultGraphCell();
                    newCell.add(new DefaultPort());
                    Map map = GraphConstants.createMap();
                    if( cellAttributes != null && !cellAttributes.isEmpty())
                    {
                        Iterator it = cellAttributes.keySet().iterator();
                        while ( it.hasNext() )
                        {
                            Object temp = it.next();
                            map.put( temp, cellAttributes.get( temp ) );
                        }
                        // This is not working here need to check later
                        //cellAttributes.putAll( map );
                    }
                    System.out.println("map.containsKey(processStepId) = " + map.containsKey("processStepId"));
                    // Make the processStepId to null
                    if( map.containsKey( "processStepId" ) )
                    {
                        //map.put( "processStepId", "" );
                        String copiedFromProcessStepId = (String)map.get( "processStepId" );
                        map.remove( "processStepId" );
                        if ( copiedFromProcessStepId != null && copiedFromProcessStepId.trim().length() > 0 )
                        {
                            Map activityAttributesMap = PopupPanel.getActivityAttributesMap( copiedFromProcessStepId, (WorkflowGraph)graph );
                            if ( activityAttributesMap != null )
                            {
                                map.putAll( activityAttributesMap );
                            }
                        }
                    }

                    // set the new cell position 20 units below the selected cell
                    if( map.containsKey("bounds")  )
                    {
                        Rectangle r = (Rectangle)map.get("bounds");
                        if ("clipboard".equalsIgnoreCase( type ) )
                        {
                            map.put( "bounds", new Rectangle( r.x, r.y+30, r.width, r.height )  );
                        }    
                        else
                        map.put( "bounds", new Rectangle( r.x, r.y+30, r.width, r.height )  );
                    }

                    // set the back ground color to blue because processStepId is null
                    GraphConstants.setBackground(map, new Color(213, 221, 253));
                    //set the attrId to be distinct
                    map.put ( "attrId", "TEMP_"+ System.currentTimeMillis() );

                    Hashtable attributes = new Hashtable();
                    attributes.put( newCell, map );
                    graph.getGraphLayoutCache().insert(
                        new Object[] { newCell },
                        attributes,
                        null,
                        null,
                        null);
                    newCellMap.put(cell, newCell);
                    newCells[i] = newCell;
                }*/
            }
            /*for ( int i=0; i < selectedEdges.length; i++ )
            {

            }*/
            graph.setSelectionCells(newCells);
        }
	}

	public void copy()
	{
		if ( !graph.isSelectionEmpty() )
		{
			selectedCells = graph.getSelectionCells();
        }
		else
		{
			selectedCells = null;
        }
	}

	//
	// Listeners
	//

	// From GraphSelectionListener Interface
	public void valueChanged(GraphSelectionEvent e) {

		// Group Button only Enabled if more than One Cell Selected
		group.setEnabled(graph.getSelectionCount() > 1);
		// Update Button States based on Current Selection
		boolean enabled = !graph.isSelectionEmpty();
		remove.setEnabled(enabled);
		ungroup.setEnabled(enabled);
		tofront.setEnabled(enabled);
		toback.setEnabled(enabled);
		copy.setEnabled(enabled);
        copyToclipboard.setEnabled( enabled );

		//cut.setEnabled(enabled);
	}

	//
	// KeyListener for Delete KeyStroke
	//
	public void keyReleased(KeyEvent e) {
	}
	public void keyTyped(KeyEvent e) {
	}
	public void keyPressed(KeyEvent e)
	{
		if ( e.getKeyCode() == KeyEvent.VK_DELETE )
		{
			//Execute Remove Action on Delete Key Press
			remove.actionPerformed(null);
		}
		else if( e.getModifiers() == KeyEvent.CTRL_MASK  && e.getKeyCode() == KeyEvent.VK_C )
		{
			e.consume();
			copy();
		}
		else if( e.getModifiers() == KeyEvent.CTRL_MASK  && e.getKeyCode() == KeyEvent.VK_V )
		{
			e.consume();
			paste(null);
		}
	}

	//
	// PopupMenu
	//
	public JPopupMenu createPopupMenu(final Point pt, final Object cell) {
		JPopupMenu menu = new JPopupMenu();
		if (cell != null) {
			// Edit
			menu.add(new AbstractAction("Edit") {
				public void actionPerformed(ActionEvent e) {
					graph.startEditingAtCell(cell);
				}
			});
		}
		// Remove
		if (!graph.isSelectionEmpty()) {
            if ( cell instanceof DefaultEdge )
            {
                menu.addSeparator();
                menu.add( new AbstractAction("Remove") {
                    public void actionPerformed(ActionEvent e) {
                        remove.actionPerformed(e);
                    }
                });
            }
            else
            {
                if ( cell != null && ( cell instanceof DefaultGraphCell ) )
                {
                    Map attributes = (( DefaultGraphCell )cell).getAttributes();
                    int processStepId = 0;
                    try {
                        processStepId = Integer.parseInt( (String)attributes.get("processStepId") );
                    }
                    catch ( NumberFormatException ignore )
                    {

                    }

                    //if ( processStepId == 0 )
                    {
                        menu.addSeparator();
                        menu.add( new AbstractAction("Remove") {
                            public void actionPerformed(ActionEvent e) {
                                remove.actionPerformed(e);
                            }
                        });
                    }
                }
            }
		}
		menu.addSeparator();
		// Insert
		menu.add(new AbstractAction("Insert") {
			public void actionPerformed(ActionEvent ev) {
				insert(pt);
			}
		});
		return menu;
	}

	//
	// ToolBar
	//
	public JToolBar createToolBar() {
		JToolBar toolbar = new JToolBar();
		toolbar.setFloatable(false);
		// Insert
		toolbar.add(new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
                insert(new Point(xCordinate, yCordinate));
                xCordinate = 10; // Reintialize
                yCordinate = 10;
			}
			public void putValue(String key, Object newValue)
			{
				URL insertUrl = getClass().getClassLoader().getResource("insert.gif");
				final ImageIcon insertIcon = new ImageIcon(insertUrl);

				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>New Activity</body></html>");
				super.putValue( Action.SMALL_ICON , insertIcon );
			}
		});

		// Toggle Connect Mode
		URL connectUrl = getClass().getClassLoader().getResource("connecton.gif");
		ImageIcon connectIcon = new ImageIcon(connectUrl);
		toolbar.add(new AbstractAction("", connectIcon) {
			public void actionPerformed(ActionEvent e) {
				graph.setPortsVisible(!graph.isPortsVisible());
				URL connectUrl;
				if (graph.isPortsVisible()){
					connectUrl = getClass().getClassLoader().getResource("connecton.gif");
				}
				else{
					connectUrl = getClass().getClassLoader().getResource("connectoff.gif");
				}
				ImageIcon connectIcon = new ImageIcon(connectUrl);
				putValue(SMALL_ICON, connectIcon);
			}

			public void putValue(String key, Object newValue)
			{
				URL connectUrl = getClass().getClassLoader().getResource("connecton.gif");
				ImageIcon connectIcon = new ImageIcon(connectUrl);
				super.putValue(SMALL_ICON, connectIcon);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Enable Transition</body></html>");
			}
		});

		SAVE = new AbstractAction("") {
			public void actionPerformed( ActionEvent e )
			{
				String msg = getGraph().getWorkflowManager().validateGraph();
				if( msg.length() > 1 )
				{
					JOptionPane.showMessageDialog( null, msg, "Chiptrac Error", JOptionPane.ERROR_MESSAGE);
				}
				else
				{
					this.setEnabled( false );
					boolean success = save( "Database" );
					if( success )
					{
						JOptionPane.showMessageDialog( null, "Saved data successfully to Database", "Chiptrac Info", JOptionPane.INFORMATION_MESSAGE );
					}
					this.setEnabled( true );
				}
			}

			public void putValue(String key, Object newValue)
			{
				URL saveUrl = getClass().getClassLoader().getResource("save.gif");
				ImageIcon saveIcon = new ImageIcon( saveUrl );
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Save to Database</body></html>");
				super.putValue( Action.SMALL_ICON , saveIcon );
			}
		};

		toolbar.add(SAVE);

		// Undo
		toolbar.addSeparator();
		undo = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				undo();
			}
			public void putValue(String key, Object newValue)
			{
				URL undoUrl = getClass().getClassLoader().getResource("undo.gif");
				ImageIcon undoIcon = new ImageIcon(undoUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Undo</body></html>");
				super.putValue( Action.SMALL_ICON , undoIcon );
			}
		};
		undo.setEnabled(false);
		toolbar.add(undo);

		// Redo
		redo = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				redo();
			}
			public void putValue(String key, Object newValue)
			{
				URL redoUrl = getClass().getClassLoader().getResource("redo.gif");
				ImageIcon redoIcon = new ImageIcon(redoUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Redo</body></html>");
				super.putValue( Action.SMALL_ICON , redoIcon );
			}
		};
		redo.setEnabled(false);
		toolbar.add(redo);

		//
		// Edit Block
		//
		toolbar.addSeparator();
		
		// Copy
		/*action = TransferHandler.getCopyAction();
		url = getClass().getClassLoader().getResource("copy.gif");
		action.putValue(Action.SMALL_ICON, new ImageIcon(url));
		action.putValue(Action.SHORT_DESCRIPTION,"<html><body bgcolor='#ffffee'>Copy</body></html>" );
		toolbar.add(copy = new EventRedirector(action));*/

		copy = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				copy();
			}

			public void putValue(String key, Object newValue)
			{
				URL copyUrl = getClass().getClassLoader().getResource("copy.gif");
				ImageIcon saveIcon = new ImageIcon( copyUrl );
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Copy</body></html>");
				super.putValue( Action.SMALL_ICON , saveIcon );
			}
		};
        copy.setEnabled( false );
		toolbar.add(copy);

		// Paste
		paste = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				paste(null);
			}

			public void putValue(String key, Object newValue)
			{
				URL saveUrl = getClass().getClassLoader().getResource("paste.gif");
				ImageIcon saveIcon = new ImageIcon( saveUrl );
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Paste</body></html>");
				super.putValue( Action.SMALL_ICON , saveIcon );
			}
		};

		toolbar.add(paste);

		// Cut
		//action = graph.getTransferHandler().getCutAction();
        /*
        action = TransferHandler.getCutAction();
		url = getClass().getClassLoader().getResource("cut.gif");
		action.putValue(Action.SMALL_ICON, new ImageIcon(url));
		action.putValue(Action.SHORT_DESCRIPTION,"<html><body bgcolor='#ffffee'>Cut</body></html>" );
		toolbar.add(cut = new EventRedirector(action));
		*/

		// Remove
		remove = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				if (!graph.isSelectionEmpty()) {
					Object[] cells = graph.getSelectionCells();  //getting all the selected cells.
                    if ( cells.length > 1 )
                    {
                        JOptionPane.showMessageDialog(null,"Please select only one process","ChipTrac Info",JOptionPane.INFORMATION_MESSAGE);
                    }
                    else
                    {
                        StringBuffer alertMsg = new StringBuffer();
                        int choice = -1;
                        DefaultGraphCell selectedCell = (DefaultGraphCell)cells[0];//since we are restricting to select only one
                        if ( selectedCell instanceof DefaultEdge )
                        {
                            //no alert msg required
                            choice = 0;//default alert passed OK
                        }
                        else
                        {
                            choice = JOptionPane.showConfirmDialog(null,"Are you sure, you want to delete the product?\nIt can not be undone.","Chiptrac Confirmation",JOptionPane.OK_CANCEL_OPTION);
                        }
                        // in case the user chooses OK
                        if ( choice == 0 )
                        {
                            ArrayList selectedEdges = new ArrayList();
                            for (int i=0; i < cells.length; i++)
                            {
                                DefaultGraphCell cell = (DefaultGraphCell)cells[i];
                                if ( cell instanceof DefaultEdge )
                                {
                                    selectedEdges.add ( cell );
                                }
                                else
                                {
                                    Map map 				 = cell.getAttributes();
                                    String processStepID  = (String)map.get("processStepId");
                                    if ( processStepID == null || processStepID.trim().length() == 0 )
                                    {
                                        processStepID = "-1";
                                    }
                                    try
                                    {
                                        String actualXPDL = getXPDL(null, null, null);
                                        Iterator edgesIterator = model.getPort(cell).edges();
                                        ArrayList edgesList = new ArrayList();
                                        while( edgesIterator.hasNext() )
                                        {
                                            DefaultEdge edge = (DefaultEdge)edgesIterator.next();
                                            edgesList.add ( edge );
                                        }
                                        //remove cell
                                        Object[] removeCells = new Object[]{cell};
                                        removeCells = graph.getDescendants(removeCells);
                                        graph.getModel().remove(removeCells);

                                        //remove edges for the cell
                                        for ( int k=0; k < edgesList.size(); k++ )
                                        {
                                            DefaultEdge edge = (DefaultEdge)edgesList.get(k);
                                            Map edmap 		 = edge.getAttributes();
                                            edmap.put ( "isRemoved", "true" );
                                            edge.setAttributes( edmap );
                                            Object[] edgeCells = new Object[]{edge};
                                            edgeCells = graph.getDescendants(edgeCells);
                                            graph.getModel().remove(edgeCells);
                                        }
                                        String deletedXPDL = getXPDL(null,null, null );
                                        //todo need to send request to server to delete process
                                        Map params = new HashMap();
                                        params.put ( "xpdl", deletedXPDL );
                                        params.put ( "processStepId", processStepID );
                                        params.put ( "baseProductName", name );
                                        String response = submitToServer( "deleteProcess", params );
                                        //todo need to show response dialogue
                                        if ( response == null || !response.startsWith( "SUCCESS" ) )
                                        {
                                            alertMsg.append ( "\n" ).append ( "Could not Delete prduct '" + map.get( "partnumber" ) + "/" + map.get( "Type" ) + "' Cause: " + response );
                                            //need to restore the actualXPDL as it is not saved successfully
                                            Document document = null;
                                            DocumentBuilderFactory dbf 	= DocumentBuilderFactory.newInstance();
                                            DocumentBuilder builder 	= dbf.newDocumentBuilder();
                                            InputSource isd = new InputSource( new StringReader(actualXPDL) );
                                            document = builder.parse( isd );

                                            ArrayList edgeList = model.getAllEdges();
                                            ArrayList activityList = model.getAllCells();

                                            Object[] edges = edgeList.toArray();
                                            edges = graph.getDescendants(edges);
                                            graph.getModel().remove(edges);

                                            Object[] activities = activityList.toArray();
                                            activities = graph.getDescendants(activities);
                                            graph.getModel().remove(activities);
                                            //getGraph().removeAll();
                                            //getGraph().invalidate();
                                            getGraph().invalidate();

                                            getGraph().createWorkflowFromDoc( document );
                                            getGraph().validate();
                                        }
                                        else //deleted successfully
                                        {
                                            alertMsg.append ( "\n" ).append ( "Deleted prduct '" + map.get( "partnumber" ) + "/" + map.get( "Type" ) + "' Successfully" );
                                        }
                                    }
                                    catch ( Exception ex )
                                    {
                                        System.out.println ( "Could not delete product" );
                                        ex.printStackTrace();
                                    }
                                }
                                //cells = graph.getDescendants(cells);
                                //graph.getModel().remove(cells);
                                /*ArrayList edgeList = model.getAllEdges();
                                for (int i = 0 ; i < edgeList.size() ; i++ )
                                {
                                    DefaultEdge edge = (DefaultEdge)edgeList.get(i);
                                    if( edge.getSource() != null )
                                    {
                                        DefaultGraphCell sourceCell = (DefaultGraphCell)((DefaultPort)edge.getSource()).getParent();
                                    }
                                    else
                                    {
                                        Object[] edgeCells = new Object[]{edge};
                                        edgeCells = graph.getDescendants(edgeCells);
                                        graph.getModel().remove(edgeCells);
                                    }

                                    if( edge.getTarget() != null )
                                    {
                                        DefaultGraphCell targetCell = (DefaultGraphCell)((DefaultPort)edge.getTarget()).getParent();
                                    }
                                    else
                                    {
                                        Object[] edgeCells = new Object[]{edge};
                                        edgeCells = graph.getDescendants(edgeCells);
                                        graph.getModel().remove(edgeCells);
                                    }
                                }*/
                            }
                            boolean isTransitionsRemovedfromDB = true;
                            for ( int i=0; i < selectedEdges.size(); i++ )
                            {
                                DefaultEdge edge = (DefaultEdge)selectedEdges.get(i);
                                Map edgeMap  = edge.getAttributes();
                                if ( !"true".equalsIgnoreCase( (String)edgeMap.get("isRemoved") ) )
                                {
                                    Object[] edgeCells = new Object[]{edge};
                                    edgeCells = graph.getDescendants(edgeCells);
                                    graph.getModel().remove(edgeCells);
                                    isTransitionsRemovedfromDB = false;
                                }
                            }
                            if ( !isTransitionsRemovedfromDB )
                            {
                                alertMsg.append( "\n" ).append( "* Some Transitions were not deleted from DB, Please click 'Save to Database' to update." );
                            }
                            JOptionPane.showMessageDialog(null,alertMsg.toString(),"ChipTrac Info",JOptionPane.INFORMATION_MESSAGE);
                        }
                    }
                }
			}
			public void putValue(String key, Object newValue)
			{
				URL removeUrl = getClass().getClassLoader().getResource("delete.gif");
				final ImageIcon removeIcon = new ImageIcon( removeUrl );
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Delete</body></html>");
				super.putValue( Action.SMALL_ICON , removeIcon );
			}
		};
		remove.setEnabled(false);
		toolbar.add(remove);

		// Zoom Std
		toolbar.addSeparator();
		//URL zoomUrl = getClass().getClassLoader().getResource("zoom.gif");
		//ImageIcon zoomIcon = new ImageIcon(zoomUrl);
		toolbar.add(new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				graph.setScale(1.0);
			}
			public void putValue(String key, Object newValue)
			{
				URL zoomUrl = getClass().getClassLoader().getResource("zoom.gif");
				ImageIcon zoomIcon = new ImageIcon(zoomUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Zoom</body></html>");
				super.putValue( Action.SMALL_ICON , zoomIcon );
			}
		});
		// Zoom In
		toolbar.add(new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				// Modified By Subramani
				graph.setScale( ( ( graph.getScale() * 10 )/100 ) + graph.getScale() );
			}
			public void putValue(String key, Object newValue)
			{
				URL zoomInUrl = getClass().getClassLoader().getResource("zoomin.gif");
				ImageIcon zoomInIcon = new ImageIcon(zoomInUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Zoom in</body></html>");
				super.putValue( Action.SMALL_ICON , zoomInIcon );
			}
		});
		// Zoom Out
		toolbar.add(new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
                // Modified By Subramani
				graph.setScale( graph.getScale() - ( ( graph.getScale() * 10 )/100 ) );
			}
			public void putValue(String key, Object newValue)
			{
				URL zoomOutUrl = getClass().getClassLoader().getResource("zoomout.gif");
				ImageIcon zoomOutIcon = new ImageIcon(zoomOutUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Zoom out</body></html>");
				super.putValue( Action.SMALL_ICON , zoomOutIcon );
			}
		});

		//Group
		toolbar.addSeparator();
		group = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				group(graph.getSelectionCells());
			}
			public void putValue(String key, Object newValue)
			{
				URL groupUrl = getClass().getClassLoader().getResource("group.gif");
				ImageIcon groupIcon = new ImageIcon(groupUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Group activity</body></html>");
				super.putValue( Action.SMALL_ICON , groupIcon );
			}
		};
		/*  Removed By Subramani
			group.setEnabled(false);
			toolbar.add(group); */

		// Ungroup
		ungroup = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				ungroup(graph.getSelectionCells());
			}
			public void putValue(String key, Object newValue)
			{
				URL ungroupUrl = getClass().getClassLoader().getResource("ungroup.gif");
				ImageIcon ungroupIcon = new ImageIcon(ungroupUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Ungroup activity</body></html>");
				super.putValue( Action.SMALL_ICON , ungroupIcon );
			}
		};
		/*  Removed By Subramani
	    	ungroup.setEnabled(false);
			toolbar.add(ungroup);*/

		// To Front
		//toolbar.addSeparator();
		tofront = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				if (!graph.isSelectionEmpty())
					toFront(graph.getSelectionCells());
			}
			public void putValue(String key, Object newValue)
			{
				URL toFrontUrl = getClass().getClassLoader().getResource("tofront.gif");
				ImageIcon toFrontIcon = new ImageIcon(toFrontUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>To front</body></html>");
				super.putValue( Action.SMALL_ICON , toFrontIcon );
			}
		};
		/* 	Removed By Subramani
	    	tofront.setEnabled(false);
			toolbar.add(tofront);*/

		//  To Back
		toback = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				if (!graph.isSelectionEmpty())
					toBack(graph.getSelectionCells());
			}
			public void putValue(String key, Object newValue)
			{
				URL toBackUrl = getClass().getClassLoader().getResource("toback.gif");
				ImageIcon toBackIcon = new ImageIcon(toBackUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>To back</body></html>");
				super.putValue( Action.SMALL_ICON , toBackIcon );
			}
		};
		/* 	Removed By Subramani
			toback.setEnabled(false);
			toolbar.add(toback);*/

		//  Save to file
		saveToFile = new AbstractAction("") {
			public void actionPerformed(ActionEvent e) {
				boolean success = save("File");
                if( success )
                {
                    JOptionPane.showMessageDialog( null, "Saved data successfully to File", "Chiptrac Info", JOptionPane.INFORMATION_MESSAGE );
                }
				//File file = new File(name+".xpdl");
				//getGraph().getWorkflowManager().saveToDB(file);
			}
			public void putValue(String key, Object newValue)
			{
				URL dbUrl =	getClass().getClassLoader().getResource("database.gif");
				ImageIcon dbIcon = new ImageIcon(dbUrl);
				super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Save to file</body></html>");
				super.putValue( Action.SMALL_ICON , dbIcon );
			}
		};
        toolbar.add( saveToFile );

        // Align
        align = new AbstractAction("") {
            public void actionPerformed(ActionEvent e) {
                align();
            }
            public void putValue(String key, Object newValue)
            {
                URL dbUrl =	getClass().getClassLoader().getResource("align.gif");
                ImageIcon dbIcon = new ImageIcon(dbUrl);
                super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Align</body></html>");
                super.putValue( Action.SMALL_ICON , dbIcon );
            }
        };
        toolbar.add( align );

        toolbar.addSeparator();
        // search
        search = new AbstractAction("") {
            public void actionPerformed(ActionEvent e)
            {
                SearchDialog searchDialog = new SearchDialog();

                searchDialog.setVisible(true);
            }
            public void putValue(String key, Object newValue)
            {
                URL dbUrl =	getClass().getClassLoader().getResource("search.gif");
                ImageIcon dbIcon = new ImageIcon(dbUrl);
                super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Search</body></html>");
                super.putValue( Action.SMALL_ICON , dbIcon );
            }
        };
        toolbar.add( search );
        // copyToclipboard
        copyToclipboard = new AbstractAction("") {
            public void actionPerformed(ActionEvent e)
            {
                copy();

                boolean success = writeToClipBoardFile();

                if( success )
                {
                    JOptionPane.showMessageDialog( null, "Copied to ClipBoard", "Chiptrac Info", JOptionPane.INFORMATION_MESSAGE );
                }

            }
            public void putValue(String key, Object newValue)
            {
                URL dbUrl =	getClass().getClassLoader().getResource("clipboard.gif");
                ImageIcon dbIcon = new ImageIcon(dbUrl);
                super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Copy To ClipBoard</body></html>");
                super.putValue( Action.SMALL_ICON , dbIcon );
            }
        };
        copyToclipboard.setEnabled( false );
        toolbar.add( copyToclipboard );
        
         // Paste clipboard
        pasteclipboard = new AbstractAction("") {
            public void actionPerformed(ActionEvent e)
            {
                try
                {
                    getGraph().createWorkflow(contextURL+"/"+URLEncoder.encode("clipboard","UTF-8")+".xpdl", "clipboard");
                    selectedCells =graph.getSelectionCells();

                    paste("clipboard");
                }
                catch( UnsupportedEncodingException uee )
                {
                    System.out.println("UnsupportedEncodingException for encoding the file name");
                }
            }
            public void putValue(String key, Object newValue)
            {
                URL dbUrl =	getClass().getClassLoader().getResource("pasteclipboard.gif");
                ImageIcon dbIcon = new ImageIcon(dbUrl);
                super.putValue( AbstractAction.SHORT_DESCRIPTION , "<html><body bgcolor='#ffffee'>Paste ClipBoard</body></html>");
                super.putValue( Action.SMALL_ICON , dbIcon );
            }
        };
        //pasteclipboard.setEnabled( false );
        toolbar.add( pasteclipboard );

        return toolbar;
	}

    public boolean writeToClipBoardFile()
    {
        ArrayList<DefaultGraphCell> cellsList = new ArrayList<DefaultGraphCell>();
        ArrayList<DefaultEdge> edgesList = new ArrayList<DefaultEdge>();
        boolean success = false;
        if( selectedCells != null && selectedCells.length > 0 )
        {
            int selectedCellsCount = selectedCells.length;

            for ( int i=0; i < selectedCellsCount; i++ )
            {
                selectedCell = selectedCells[i];
                if ( selectedCell instanceof DefaultEdge )
                {
                    DefaultEdge edge = (DefaultEdge)selectedCell;
                    
                    edgesList.add( edge );
                }
                else if( selectedCell instanceof DefaultGraphCell )
                {
                    DefaultGraphCell cell = (DefaultGraphCell)selectedCell;
                    cellsList.add( cell );
                }
            }

            if ( cellsList.size() == 1 && edgesList.size() == 1 )
            {
                JOptionPane.showMessageDialog( null, "Please select the More Cells", "Chiptrac Info", JOptionPane.INFORMATION_MESSAGE );
                return success;
            }
            //Edges for loop

            success = save("ClipBoard", cellsList, edgesList);
	    }
        else
        {
            JOptionPane.showMessageDialog( null, "Please select the More Cells", "Chiptrac Info", JOptionPane.INFORMATION_MESSAGE );
            return success;
        }
        
        return success;
    }//eND of METHOD WriteToClipBoard File

	// This will change the source of the action event to graph.
	protected class EventRedirector extends AbstractAction {

		protected Action action;

		// Construct the "Wrapper" Action
		public EventRedirector( Action a )
		{
			super( "", ( ImageIcon ) a.getValue( Action.SMALL_ICON ) );
			this.action = a;
		}

		// Redirect the Actionevent
		public void actionPerformed(ActionEvent e) {
			e =
				new ActionEvent(
					graph,
					e.getID(),
					e.getActionCommand(),
					e.getModifiers());
			action.actionPerformed(e);
		}
	}

    public void mouseEntered(MouseEvent me){}
    public void mouseExited(MouseEvent me){}
    public void mousePressed(MouseEvent me){}
    public void mouseReleased(MouseEvent me){}
    public void mouseClicked(MouseEvent me)
    {
        xCordinate = me.getX();
        yCordinate = me.getY();
    }

    public HashMap getNewPartNumberMap()
    {
        return newPartNumberMap;
    }

    public void setNewPartNumberMap(HashMap map)
    {
        newPartNumberMap = map;
    }
    
    protected class SearchDialog extends JDialog
                   implements ActionListener, PropertyChangeListener
    {
        private JTextField textField;
        private JOptionPane optionPane;
        private String searchBttn = "Search";
        private String resetBttn = "Reset";
        private String cancelBttn = "Cancel";
        private SearchDialog()
        {           
            super((Frame) null, true);
            setTitle("Chiptrac Find");
            textField = new JTextField(10);
            //Create an array of the text and components to be displayed.
            String msgString1 = "Find Part Number:";
            Object[] array = {msgString1, textField};

            //Create an array specifying the number of dialog buttons
            //and their text.
            Object[] options = { searchBttn, resetBttn, cancelBttn };
            URL dbUrl =	getClass().getClassLoader().getResource("search.gif");
            ImageIcon searchIcon = new ImageIcon(dbUrl);
            //Create the JOptionPane.
            optionPane = new JOptionPane(array,
                                    JOptionPane.QUESTION_MESSAGE,
                                    JOptionPane.YES_NO_CANCEL_OPTION,
                                    searchIcon,
                                    options,
                                    options[0]);
            //Make this dialog display it.
            setContentPane(optionPane);
            //Handle window closing correctly.
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent we) {
                /*
                 * Instead of directly closing the window,
                 * we're going to change the JOptionPane's
                 * value property.
                 */
                    optionPane.setValue(new Integer(
                                        JOptionPane.CLOSED_OPTION));
                }
            });
            //Ensure the text field always gets the first focus.
            addComponentListener(new ComponentAdapter() {
                public void componentShown(ComponentEvent ce) {
                    textField.requestFocusInWindow();
                }
            });

            //Register an event handler that puts the text into the option pane.
            textField.addActionListener(this);
            //Register an event handler that reacts to option pane state changes.
            optionPane.addPropertyChangeListener(this);

            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            setBounds((int)(screenSize.getWidth()-300)/2, (int)(screenSize.getHeight()-130)/2, 300, 130);
            setResizable(false);
        }        
        /** This method handles events for the text field. */
        public void actionPerformed(ActionEvent e)
        {
            optionPane.setValue( searchBttn );
        }
         /** This method reacts to state changes in the option pane. */
        public void propertyChange(PropertyChangeEvent e)
        {
            String prop = e.getPropertyName();
            if (isVisible() && (e.getSource() == optionPane) && (JOptionPane.VALUE_PROPERTY.equals(prop) ||
                 JOptionPane.INPUT_VALUE_PROPERTY.equals(prop) ) )
            {
                Object value = optionPane.getValue();
                if (value == JOptionPane.UNINITIALIZED_VALUE) {
                    //ignore reset
                    return;
                }
                //Reset the JOptionPane's value.
                //If you don't do this, then if the user
                //presses the same button next time, no
                //property change event will be fired.
                optionPane.setValue(
                        JOptionPane.UNINITIALIZED_VALUE);
                if ( searchBttn.equals(value) )
                {
                    String typedText = textField.getText();
                    if ( typedText != null && typedText.length() > 0 )
                    {
                        if( search(typedText) )
                        {
                            //we're done; clear and dismiss the dialog
                            clearAndHide();
                        }
                        else
                        {
                            //text was invalid
                            textField.selectAll();
                            JOptionPane.showMessageDialog( SearchDialog.this,
                                            "Cannot find part number \"" + typedText + "\"",
                                            "Try again",
                                            JOptionPane.INFORMATION_MESSAGE );
                            typedText = null;
                            textField.requestFocusInWindow();
                        }
                    }
                }
                else if ( resetBttn.equals( value ) )
                {
                    textField.setText(null);
                    search(null); //resetting border color
                    textField.requestFocusInWindow();
                }
                else
                {
                    clearAndHide();
                }
            }
        }

        /** This method clears the dialog and hides it. */
        public void clearAndHide()
        {
            //textField.setText(null);
            //setVisible(false);
            dispose();
        }
    }
    private String submitToServer( String actionName, Object params )
    {
        URL url;								                        // URL to connect.
		URLConnection con 	= null;				                        // Connection Object to connect to URL.
		String str = "saveActivityAttributes";// + separator + graph.getEditor().getName();	// This is the key specifying the DATA required.
        ObjectOutputStream outStream 	= null;                         // Byte Stream to write into
		ObjectInputStream inputToApplet = null;	                        // Byte Stream to read from
        String response = "";
		try
		{
			// Connect to com.scalar.chiptrack.operations.process.WorkFlowAction
			// The servlet used to fetch data
			url = new URL( this.getContextURL()+"/WorkflowServlet" );
			// Open the Connection to the URL
			con = url.openConnection();

			if ( !con.getDoOutput() )
			{
				con.setDoOutput( true );
			}
			con.setDoInput( true );
			con.setUseCaches ( false );
			con.setDefaultUseCaches ( false );
			con.setAllowUserInteraction( true );
			// Set the Content length to the length of data u supose to write to Connection
			con.setRequestProperty ( "CONTENT_LENGTH", "" + str.length() );
			con.setRequestProperty ( "Content-Type", "application/octet-stream" );
			// Connect to the URL
			con.connect();
			// Get the ObjectOutputStream send information to servlet
			outStream = new ObjectOutputStream( con.getOutputStream() );
			// Write the required information to the ObjectOutputStream.
			outStream.writeObject( actionName );
			outStream.writeObject( params );
			outStream.flush();
			outStream.close();
            outStream = null;

            // Fetch the ObjectInputStream from the connection.
			inputToApplet = new ObjectInputStream( con.getInputStream() );
			try
			{
				// Read the information Fetched from the Servlet
				response = (String) inputToApplet.readObject();
			}
			catch ( Exception e2 )
			{
				e2.printStackTrace();
			}
		}
		catch ( Exception e )
		{
			e.printStackTrace();
		}
        finally
        {
            if ( outStream != null )
            {
                try { outStream.close(); outStream = null; } catch ( IOException ignore ) {}
            }
            if ( inputToApplet != null )
            {
                try { inputToApplet.close(); inputToApplet = null; } catch ( IOException ignore ) {}
            }
        }
        return response;
    }
}